const router = require("express").Router();
const axios = require("axios");
var WXBizDataCrypt = require("../../../../tools/WXBizDataCrypt");
const UserModel = require("../../../../model/schema/userModel");
var jwt = require("jsonwebtoken");
const { wxConfig } = require("../../../../config/config");

const appId = wxConfig.appId; // 自己的小程序 appId
const secret = wxConfig.secret; // 自己的 小程序 appSecret 密钥来着
var js_code = ""; // 登陆者的临时凭证code
const grant_type = wxConfig.grant_type; // 授权类型，此处只需填写 authorization_code

router.get("/", async(req, res) => {
    // console.log(req.query);
    js_code = req.query.code;

    const { data: result } = await axios.get(
        `https://api.weixin.qq.com/sns/jscode2session?appid=${appId}&secret=${secret}&js_code=${js_code}&grant_type=${grant_type}`
    );
    // console.log(result);

    var loginResult = {};

    if (!result) {
        // 如果获取不到用户数据，说明前端传过来的 code 失效或者无效
        loginResult = {
            meta: {
                status: 404,
                msg: "登录失败, code无效",
            },
            message: {},
        };
    } else {
        // 成功获取到code值
        // 查找 user_info表 中是否存在该用户的 openid
        // 如果有的话则返回对应的token数据。 token数据里面包含了它在表中的 ObjectId，用来唯一标识该用户
        // 如果没有的话则创建该用户信息进 user_info表 并且 返回token数据

        const hasOne = await UserModel.findOne({
            openid: result.openid,
        });
        // console.log(hasOne._id.toString()); // hasOne._id 是一个new Object('xxxx') 需要 toString() 拿到里面的字符串
        var userInfo = {};

        // 如果没有则添加该用户进入user_info表中
        if (!hasOne) {
            var encryptedData = req.query.encryptedData; // 加密过后的用户普通信息和某些敏感信息
            var session_key = result.session_key; // 用户登录该小程序的会话key，相当于登录该小程序的密码
            var iv = req.query.iv; // 用于配合encryptedData解密

            var pc = new WXBizDataCrypt(appId, session_key); // 解密类
            var decodeInfo = pc.decryptData(encryptedData, iv); // 之所以使用这个方法获取用户普通信息和某些敏感信息，是怕获取时被篡改导致拿不到准确的信息。里面有个敏感信息是 watermark节点下的信息
            // console.log("encryptedData解密后 decodeInfo: ", decodeInfo);
            var newUserInfo = Object.assign(result, decodeInfo); // 合并对象
            // console.log(newUserInfo);
            const rebackUserInfo = await new UserModel(newUserInfo).save(); // 添加完并成功后会返回一个添加好的对象
            // 添加完后拿到它的_id
            userInfo = {
                _id: rebackUserInfo._id.toString(),
            };
        } else {
            // 存在则直接拿存在的 _id 就行
            userInfo = {
                _id: hasOne._id.toString(),
            };
        }

        loginResult = {
            meta: {
                status: 200,
                msg: "登录成功",
            },
            message: {
                token: jwt.sign(userInfo, secret, { expiresIn: "1day" }), // 对 _id 进行一个 jwt 加密，然后再返回给用户，等到用户携带回来的时候进行解密然后根据_id匹配数据
                // token: jwt.sign(userInfo, result.session_key, { expiresIn: "1day" }), // 可以选择用户的 会话session密钥，当这个密钥过期之后需要重新登录
            },
        };
    }
    // 返回携带token的数据对象
    res.jsonp(loginResult);

    /**
     * jwt解密, 注意 加密和解密时 secret 需要一致
     */
    // jwt.verify(userToken, secret, (err, result) => {
    //     if (err) {
    //         // throw err 说明用户的 session_key 过期，需要重新登录
    //         res.json({ msg: "无效的token或token已过期" });
    //     } else {
    //         res.json(result);
    //     }
    // });

    /**
     * 后面如果用户携带token返回时，我们可以在前端先wx.login()拿到code, 根据code拿到用户 session_key, 然后进行对token 用jwt解密, 从而拿到该用户在user_info表中的_id
     * 如果解密失败，要么是无效的token, 要么就是session_key变化了说明用户的token已过期需要重新登录
     * token的作用就是标识用户在表中的唯一标识，也就是证明用户在服务器身份的一个东西，当用户在该小程序的session_key会话变化时，该token就会失效，或者用户删除掉token也会导致token失效
     */
});

module.exports = router;